package niuniu

import (
	"errors"
	"fmt"
	"gitee.com/yuya000/cards-game-server-go/logwarp"
	"gitee.com/yuya000/cards-game-server-go/server"
	"github.com/BurntSushi/toml"
	"strconv"
	"strings"
)

const (
	GameName = "niuniu"
)

type GameConfig struct {
	Name string `xorm:"name"`
	Help string `xorm:"help"`
	Conf string `xorm:"conf"`
	Opt  string `xorm:"opt"`
}

type NiuNiuOpt struct {
	GameType     string   `toml:"type"`           // 游戏类型
	CostAndRound []string `toml:"cost_and_round"` // 花费 1 2 3
	Zhuang       []string `toml:"zhuang"`         // 抢庄 房主庄
	Rules        []string `toml:"rules"`          // 金牛 银牛 比花色
	Comment      string   `toml:"comment"`        // 备注 2人即可游戏，最多6人
}

type NiuniuConf struct {
	maxRound    int
	cost        int
	qiangzhuang bool
	jinniu      bool
	yinniu      bool
	bihuase     bool
	MinPlayerN  int `toml:"min_players"`
	MaxPlayerN  int `toml:"max_players"`
}

func NewNiuNiuConf(args server.Args) (*NiuniuConf, error) {
	var (
		gc   GameConfig
		conf NiuniuConf
		opt  NiuNiuOpt
	)
	exist, err := server.DBEngine.Where("name=?", GameName).Get(&gc)
	if err != nil {
		return nil, err
	}
	if !exist {
		return nil, errors.New("游戏配置不存在")
	}
	if err := toml.Unmarshal([]byte(gc.Conf), &conf); err != nil {
		return nil, err
	}
	if err := toml.Unmarshal([]byte(gc.Opt), &opt); err != nil {
		return nil, err
	}
	if len(args["round"]) != 1 || args["round"][0] >= len(opt.CostAndRound) {
		logwarp.Std().Warningln("参数错误 round", args["round"])
		return nil, fmt.Errorf("参数错误 round %v", args["round"])
	}
	optIndex := args["round"][0]
	selectedCostAndRound := opt.CostAndRound[optIndex]
	cost_round := strings.Split(selectedCostAndRound, "-")
	if len(cost_round) != 2 {
		logwarp.Std().Warningln("参数错误 round", cost_round)
		return nil, fmt.Errorf("参数错误 round %v", cost_round)
	}
	if conf.maxRound, err = strconv.Atoi(cost_round[0]); err != nil {
		logwarp.Std().Warningln("参数错误 round", cost_round[0])
		return nil, fmt.Errorf("参数错误 round %v", cost_round[0])
	}
	if conf.cost, err = strconv.Atoi(cost_round[1]); err != nil {
		logwarp.Std().Warningln("参数错误 round", cost_round[1])
		return nil, fmt.Errorf("参数错误 round %v", cost_round[1])
	}
	if len(args["zhuang"]) != 1 {
		logwarp.Std().Warningln("参数错误 zhuang", args["zhuang"])
		return nil, fmt.Errorf("参数错误 zhuang %v", args["zhuang"])
	}
	zhuang := args["zhuang"][0]
	switch zhuang {
	case 0:
		conf.qiangzhuang = true
	case 1:
		conf.qiangzhuang = false
	default:
		logwarp.Std().Warningln("参数错误 zhuang", zhuang)
		return nil, fmt.Errorf("参数错误 zhuang %v", zhuang)
	}
	if len(args["rules"]) == 0 {
		logwarp.Std().Warningln("参数错误 rules", args)
		return nil, fmt.Errorf("参数错误 rules %v", args)
	}
	rules := args["rules"]
	for _, rule := range rules {
		switch rule {
		case 0:
			conf.jinniu = true
		case 1:
			conf.yinniu = true
		case 2:
			conf.bihuase = true
		default:
			logwarp.Std().Warningln("参数错误 rules", rule)
			return nil, fmt.Errorf("参数错误 rules %v", rule)
		}
	}
	return &conf, nil
}

type NiuNiuFactory struct{}

func (f *NiuNiuFactory) NewGame(player *server.Player, args server.Args) (server.Game, server.Exception) {
	id, err := server.GenerateGameID()
	if err != nil {
		logwarp.Std().Warningln(err)
		return nil, server.SystemException
	}
	if err := server.SendOK(player.Session, &server.NewGameResp{
		HouseNo: id,
	}, server.MessageTypeCreateGame); err != nil {
		logwarp.Std().Warningln(err)
	}
	niuniu := &NiuNiu{
		id:                id,
		name:              GameName,
		Owner:             player,
		players:           server.NewPlayerMap(),
		ReadyPlayers:      server.NewPlayerMap(),
		Stake:             make(map[string]int),
		PlayerHoldingPais: make(map[string]map[Pai]string),
		args:              args,
		ChuPai:            make(map[string]*ChuPaiCombination),
		GameExitBallotBox: make(map[string]string),
		Round:             1,
		Stat:              StatusWaiting,
	}
	conf, err := NewNiuNiuConf(args)
	if err != nil {
		logwarp.Std().Warningln(err)
		return nil, server.ArgsException
	}
	niuniu.Conf = conf
	niuniu.MaxRound = conf.maxRound
	niuniu.QiangZhuang = conf.qiangzhuang
	niuniu.CostCards = conf.cost
	niuniu.Jinniu = conf.jinniu
	niuniu.Yinniu = conf.yinniu
	niuniu.Bihuase = conf.bihuase
	niuniu.players.Store(player.Id, player)
	return niuniu, nil
}

func (f *NiuNiuFactory) Free(game server.Game) {}
